<?php
/**
 * Created by PhpStorm.
 * User: Steven
 * Date: 2017/6/19
 * Time: 9:30
 */

namespace app\course\model;


use app\classes\model\ClassModel;
use think\Db;
use think\Log;
use think\Model;

class CourseScheduleModel extends Model
{
    public function __construct($data = [])
    {
        parent::__construct($data);
    }

    /**
     * 获取排课列表
     * @param array $filter
     * @param array $order
     * @param int $limit
     * @param $query
     * @return \think\Paginator
     */
    public function getSchedule($filter=[], $order=[], $limit=10, $query)
    {
        //默认条件
        $where = [];
        if(!empty($filter) && is_array($filter)){
            $where = array_merge($where,$filter);
        }

        //默认排序
        $sort = ['crs.schedule'=>'asc'];
        if(!empty($order) && is_array($order)){
            $sort = array_merge($order,$sort);
        }

        //分页url额外参数
        $page_query['query'] = [];
        if(!empty($query) && is_array($query)){
            $page_query['query'] = $query;
        }

        $data = $this->alias('crs')
            ->field('crs.*,sc.name as school_name,cl.name as class_name,clr.name as classroom_name,cr.course_hour,cr.course_name,u.realname as user_name')
            ->join('class cl','crs.class_id=cl.id')
            ->join('classroom clr','crs.classroom_id=clr.id')
            ->join('school sc','cl.school_id=sc.id')
            ->join('course cr','cl.course_id=cr.id')
            ->join('user u', 'crs.teacher_id=u.id')
            ->where($where)
            ->order($sort)
            ->paginate($limit,false,$page_query);

        return $data;
    }

    /**
     * 添加排课
     * @param array $data
     * @return bool
     */
    public function addSchedule($data=[])
    {
        $result = true;
        if(empty($data)){
            $result = false;
        }else{
            self::startTrans();
            try{
                $this->allowField(true)->insertAll($data);

                self::commit();
            }catch(\Exception $e){
                self::rollback();
                $result = false;
            }
        }

        return $result;
    }

    /**
     * @param $id
     * @param $cur_time
     * @return bool
     */
    public function deleteSchedule($id, $cur_time)
    {
        $result = true;
        if(empty($id)){
            $result = false;
        }else{
            if(empty($cur_time)){
                //当前时间
                $cur_time = time();
            }
            if(is_array($id)){
                //批量删除
                self::startTrans();
                try{
                    $this->where(['id' => ['in', $id]])->delete();

                    self::commit();
                }catch(\Exception $e){
                    self::rollback();
                    $result = false;
                }
            }else{
                //单一删除
                self::startTrans();
                try{
                    $this->where(['id' => $id])->delete();

                    self::commit();
                }catch(\Exception $e){
                    self::rollback();
                    $result = false;
                }
            }
        }

        return $result;
    }

    /**
     * 重新排课(从指定日期开始排课)
     * @param int $date_timestamp
     * @param int $shop_id
     * @param string $msg 提示消息
     * @return bool
     */
    public function reSchedules($date_timestamp=0, $shop_id=1, &$msg)
    {
        $result = true;
        $class_ids = [];//班级ID
        $adjust_mdl = new CourseAdjustModel();//调课模型
        $class_mdl = new ClassModel();//班级模型

        if(empty($date_timestamp)){
            $msg = '假期开始时间不能为空';
            return false;
        }

        //获取当日之后的所有排课情况
        $schedules = $this->alias('cs')
            ->field('cs.id,cs.class_id')
            ->join('class cl', 'cs.class_id=cl.id')
            ->where('cl.shop_id', '=', $shop_id)
            ->where('cs.schedule', '<>', 0)//非临时加课
            ->where('cs.date', '>= time', $date_timestamp)
            ->group('cs.class_id')//以班级分组
            ->select();

        if(!$schedules->isEmpty()){
            $schedules = $schedules->toArray();
            $class_ids = array_column($schedules,'class_id');
        }

        if(count($class_ids) > 0 ) {
            self::startTrans();
            try{
                foreach ($class_ids as $val) {
                    //获取开始的进度
                    $schedule_single = $this->where('class_id', '=', $val)
                        ->where('schedule', '<>', 0)//非临时加课
                        ->where('date', '>= time', $date_timestamp)
                        ->order('schedule','asc')
                        ->find();
                    if(count($schedule_single) > 0){
                        //开始进度值
                        $schedule_num = $schedule_single['schedule'];
                    }else{
                        $schedule_num = 0;
                    }

                    //获取调课时间
                    $adjust_data = $adjust_mdl->where('class_id', '=', $val)->find();
                    if (count($adjust_data) > 0) {
                        //调课时间
                        $adjust_date[0] = $adjust_data['start_date'];
                        $adjust_date[1] = $adjust_data['end_date'];
                    } else {
                        $adjust_date = [];
                    }

                    //从当日后重新排课
                    $course_schedules = $class_mdl->getCourseTime($val, $date_timestamp, 0, $shop_id, $adjust_date, $schedule_num, $msg);
                    if (count($course_schedules) > 0) {
                        //先删除原有的排课
                        $this->where('class_id', '=', $val)
                            ->where('schedule', '<>', 0)//非临时加课
                            ->where('date', '>= time', $date_timestamp)
                            ->delete();

                        //保存新排课
                        $new_data = [];
                        foreach ($course_schedules as $k => $v) {
                            $new_data[$k] = [
                                'class_id' => $v['class_id'],
                                'classroom_id' => $v['classroom_id'],
                                'teacher_id' => $v['teacher_id'],
                                'date' => strtotime($v['date']),
                                'start_time' => $v['start_time'],
                                'end_time' => $v['end_time'],
                                'week' => $v['cur_week'],
                                'schedule' => $v['schedule'],
                            ];
                        }
                        $result = $this->addSchedule($new_data);
                        if (!$result) {
                            exception('排课失败');
                            $result = false;
                            $msg = '排课失败';
                        }
                    }
                }

                self::commit();
            }catch(\Exception $e){
                self::rollback();
                $result = false;
            }
        }
        return $result;
    }

    /**
     * 调课(插课：总课时数不变,增加新课调整进度)
     * @param int $class
     * @param int $teacher
     * @param int $classroom
     * @param array $datetime
     * @return bool|\think\response\Json
     */
    public function adjustCourse($class=0, $teacher=0, $classroom=0, $datetime=[], &$msg)
    {
        $result = true;
        //中文星期
        $gb_week = [
            '1' => '周一','2' => '周二','3' => '周三','4' => '周四',
            '5' => '周五','6' => '周六','7' => '周日',
        ];

        if(empty($class) || !is_numeric($class)){
            $msg = '班级不能为空';
            return false;
        }
        if(empty($teacher) || !is_numeric($teacher)){
            $msg = '老师不能为空';
            return false;
        }
        if(empty($classroom) || !is_numeric($classroom)){
            $msg = '教室不能为空';
            return false;
        }
        if(empty($datetime)){
            $msg = '课时不能为空';
            return false;
        }
        //排序
        sortArrByField($datetime,'date');
        //要调课的课时总数
        $total = count($datetime);

        self::startTrans();
        try{
            for($i=0; $i<$total; $i++) {
                //插入数据库标记
                $is_insert = 0;
                //获取该班级排课开始时间(若日期相同则按开始时间升序)
                $min_date = $this->where('class_id', '=', $class)
                    ->where('schedule', '>',0)
                    ->order(['date'=>'asc','start_time'=>'asc'])
                    ->find();

                //获取结课时间
                $max_date = $this->where('class_id', '=', $class)
                    ->where('schedule', '>',0)
                    ->order(['date'=>'desc','start_time'=>'desc'])
                    ->find();

                if (($datetime[$i]['date'] < $min_date['date']) || ($datetime[$i]['date'] < time())) {
                    $msg = '日期不能小于开课时间和今日时间';
                    $result = false;
                    exception('排课异常');
                }
                if(($datetime[$i]['date'] >= $max_date['date']) && ($datetime[$i]['start_time'] >= $max_date['start_time'])){
                    $msg = '日期不能大于结课时间';
                    $result = false;
                    exception('排课异常');
                }

                //获取课时
                $schedule = $this->where('class_id', '=',$class)
                    ->where('classroom_id', '=',$classroom)
                    ->where('teacher_id', '=',$teacher)
                    ->where('date', '=',$datetime[$i]['date'])
                    ->where('start_time', '=',$datetime[$i]['start_time'])
                    ->where('end_time', '=',$datetime[$i]['end_time'])
                    ->find();
                if(isset($schedule['id']) && !empty($schedule['id'])) {
                    //已存在
                    continue;
                }else{
                    //获取大于等于要插入课时的排课信息
                    $schedules = $this->where('class_id', '=',$class)
                        ->where('date', '>=',$datetime[$i]['date'])
                        ->where('schedule', '>',0)
                        ->order(['schedule'=>'asc'])
                        ->select();
                    if(count($schedules) < 1){
                        $msg = '已过期请重新提交请求';
                        $result = false;
                        exception('排课异常');
                    }else{
                        $schedules = $schedules->toArray();
                        $adjust_total = count($schedules);

                        for($j=0; $j<$adjust_total; $j++){
                            if( ($schedules[$j]['date'] == $datetime[$i]['date']) && ($schedules[$j]['start_time'] == $datetime[$i]['start_time']) ){
                                //课时相同就更新
                                $up_data = [
                                    'classroom_id' => $classroom,
                                    'teacher_id' => $teacher,
                                    'end_time' => $datetime[$i]['end_time'],
                                ];
                                $this->where(['class_id'=>$class])->update($up_data);
                                break;

                            }else{
                                if($is_insert == 0){
                                    //保存新课时
                                    $week_num = date('N', $datetime[$i]['date']);
                                    //新增调课
                                    $data['class_id'] = $class;
                                    $data['classroom_id'] = $classroom;
                                    $data['teacher_id'] = $teacher;
                                    $data['date'] = $datetime[$i]['date'];
                                    $data['start_time'] = $datetime[$i]['start_time'];
                                    $data['end_time'] = $datetime[$i]['end_time'];
                                    $data['week'] = $gb_week[$week_num];

                                    if(($schedules[$j]['date'] == $datetime[$i]['date']) && ($schedules[$j]['start_time'] < $datetime[$i]['start_time'])){
                                        $data['schedule'] = $schedules[$j]['schedule'] + 1;
                                    }else{
                                        $data['schedule'] = $schedules[$j]['schedule'];
                                        //更新
                                        $this->where(['id'=>$schedules[$j]['id']])->setInc('schedule');
                                    }

                                    //添加课时
                                    $this->insert($data);

                                    //从数据库中删除最后一节排课
                                    $item = $adjust_total-1;
                                    $schedule_id = $schedules[$item]['id'];
                                    $this->where(['id'=>$schedule_id])->delete();

                                    //从数组中删除最后一个元素
                                    array_pop($schedules);
                                    $adjust_total = count($schedules);

                                    $is_insert = 1;
                                }else{
                                    //更新
                                    $this->where(['id'=>$schedules[$j]['id']])->setInc('schedule');
                                }
                            }
                        }
                    }
                }

            }
            self::commit();

        }catch(\Exception $e){
            $result = false;
            self::rollback();
        }

        return $result;
    }

}